/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package stud.cp.user.admin;

import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import stud.cp.core.dbaccess.DAOException;
import stud.cp.core.plugins.PluginConst;
import stud.cp.core.plugins.PluginRouter;
import stud.cp.core.plugins.WrongPageRequest;
import stud.cp.user.dbaccess.*;
import stud.cp.user.valueobjects.*;

/**
 * Плагин, который осуществляет работу с пользователями.
 *
 * @author Morfant
 */
@Stateless
public class AdminPluginBean implements AdminPluginLocal {

    private BigInteger namePropertyId = new BigInteger("1");
    private BigInteger passwordPropertyId = new BigInteger("2");
    private BigInteger typePropertyId = new BigInteger("3");
    /**
     * Фабрика DAO классов.
     */
    private OracleDAOFactory oracleDAOFactory = null;
    /**
     * Логгер.
     */
    private static Logger logger = Logger.getLogger("ACPII");

    /**
     * Метод, реализующий основную бизнеслогику.
     *
     * @param req Реквест.
     * @return Класс роутер.
     */
    @Override
    public PluginRouter perform(HttpServletRequest req) {
        String subaction = req.getParameter(PluginConst.SUBACTION);
        if ((subaction != null) && (!subaction.equals(""))) {
            try {
                oracleDAOFactory = new OracleDAOFactory();
                oracleDAOFactory.initialize();

                /*
                 * Список действий которые могут выполниться.
                 */
                /*
                 * Список данных
                 */
                if (subaction.equals(PluginConst.GET_LIST)) {
                    return getListPage(req);
                }

                /*
                 * Страница добавления
                 */
                if (subaction.equals(PluginConst.GET_ADD_PAGE)) {
                    return getAddPage(req);
                }

                /*
                 * Добавление новых данных
                 */
                if (subaction.equals(PluginConst.NEW_DATA)) {
                    return newData(req);
                }

                /*
                 * Страница редактирования
                 */
                if (subaction.equals(PluginConst.GET_EDIT_PAGE)) {
                    return getEditPage(req);
                }

                /*
                 * Сохранение измененных данных
                 */
                if (subaction.equals(PluginConst.SAVE_DATA)) {
                    return saveData(req);
                }

                /*
                 * Страница удаления
                 */
                if (subaction.equals(PluginConst.GET_DELETE_PAGE)) {
                    return getDeletePage(req);
                }

                /*
                 * Удаление данные
                 */
                if (subaction.equals(PluginConst.DELETE_DATA)) {
                    return deleteData(req);
                }
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Действия для данного типа поддействия не найдено. Тип поддействия = " + subaction);
            } catch (DAOException ex) {
                logger.debug("Error due access to database. "
                        + "Plugin = PropertyGroupPluginBean. "
                        + "Subaction=" + subaction, ex);
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Ошибка доступа к данным. " + ex.getMessage());
            } catch (WrongPageRequest ex) {
                req.setAttribute(PluginConst.ERROR_MESSAGE,
                        "Данные из реквеста ошибочны :\n" + ex.getMessage());
            } finally {
                if (oracleDAOFactory != null) {
                    try {
                        oracleDAOFactory.cleanUp();
                    } catch (DAOException ex) {
                        logger.debug("Error due access to database. "
                                + "Plugin = PropertyGroupPluginBean. "
                                + "Subaction=" + subaction, ex);
                        req.setAttribute(PluginConst.ERROR_MESSAGE,
                                "Ошибка доступа к данным. " + ex.getMessage());
                    }
                }
            }
        } else {
            req.setAttribute(PluginConst.ERROR_MESSAGE,
                    "Тип поддействия не задан.");
        }
        return new PluginRouter("/errorpage.jsp");
    }

    /**
     * Метод, который позволяет получить список данных запрашиваемого типа.
     *
     * @param req Реквест.
     * @return PluginRouter на страницу в который будет выводиться список.
     * @throws DAOException Ошибки доступа к базе данных.
     */
    private PluginRouter getListPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        req.setAttribute(PluginConst.USERS_LIST, oracleDAOFactory.getUserDAO().getAll());
        return new PluginRouter("/Users/UsersTable.jsp");
    }

    /**
     * Метод, который позволяет получить страницу добавления.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     */
    private PluginRouter getAddPage(HttpServletRequest req) throws DAOException {
        req.setAttribute(PluginConst.USER_TYPES_LIST, oracleDAOFactory.getUserTypesDAO().getAll());
        return new PluginRouter("/Users/AddUser.jsp");
    }

    /**
     * Метод, позволяющий добавлять новые данные.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter newData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String name = req.getParameter(PluginConst.USER_NAME);
        String password = req.getParameter(PluginConst.USER_PASSWORD);
        String user_type_id = req.getParameter(PluginConst.USER_TYPE_ID);
        /*
         * Группа проверок на заполненность данных.
         */
        String error_message = "";

        if ((user_type_id == null)) {
            throw new WrongPageRequest("ID типа пользователя не задан.");
        }

        if ((name == null) || (name.equals(""))) {
            error_message = "Имя пользователя должно быть заполнено. ";
        }

        if ((password == null) || (password.equals(""))) {
            error_message = "Пароль должен быть заполнен. ";
        }

        if (error_message.equals("")) {
            DBObjectType objectType =
                    oracleDAOFactory.getObjectTypesDAO().
                    getById(new BigInteger(PluginConst.USER_OBJECT_TYPE_ID.toString()));

            BigInteger object_id =
                    oracleDAOFactory.getObjectDAO().
                    create(new DBObject(objectType.getObject_type_id(), name, ""));
            ParametersDAO propertyValueDAO = oracleDAOFactory.getParameterDAO();

            propertyValueDAO.create(new Parameter(namePropertyId, name, object_id, null));
            propertyValueDAO.create(new Parameter(passwordPropertyId, password, object_id, null));
            propertyValueDAO.create(new Parameter(typePropertyId, "", object_id, new BigInteger(user_type_id)));

            //TODO::[High] добавить код, которые переносит данные в историю.

//            oracleDAOFactory.getUserDAO().create(new User(new BigInteger(user_type_id), name, password));
            return new PluginRouter("admin-action.do"
                    + "?"
                    + PluginConst.SUBACTION
                    + "="
                    + PluginConst.GET_LIST, false);
        } else {
            req.setAttribute(PluginConst.ERROR_MESSAGE, error_message);
            return getAddPage(req);
        }
    }

    /**
     * Метод, который позволяет перейти на страницу редактирования данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getEditPage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String user_id = req.getParameter(PluginConst.USER_ID);
        if (user_id != null) {
            User user = null;
            user = oracleDAOFactory.getUserDAO().getById(new BigInteger(user_id));
            if (user != null) {
                req.setAttribute(PluginConst.USER, user);
                req.setAttribute(PluginConst.USER_TYPES_LIST, oracleDAOFactory.getUserTypesDAO().getAll());
            } else {
                throw new WrongPageRequest("Пользователя с таким id=" + user_id + " не существует. ");
            }
            return new PluginRouter("/Users/EditUser.jsp");
        } else {
            throw new WrongPageRequest("ID группы атрибутов не заданно.");
        }
    }

    /**
     * Сохранение данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter saveData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String name = req.getParameter(PluginConst.USER_NAME);
        String password = req.getParameter(PluginConst.USER_PASSWORD);
        String user_type_id = req.getParameter(PluginConst.USER_TYPE_ID);
        String user_id = req.getParameter(PluginConst.USER_ID);
        /*
         * Группа проверок на заполненность данных.
         */
        String error_message = "";

        if ((user_type_id == null)) {
            error_message = error_message + "ID типа пользователя не заданно. ";
        }

        if ((user_id == null)) {
            error_message = error_message + "ID пользователя не заданно. ";
        }

        if (!error_message.equals("")) {
            throw new WrongPageRequest(error_message);
        }

        if ((name == null) || (name.equals(""))) {
            error_message = "Имя пользователя должно быть заполнено. ";
        }

        if ((password == null) || (password.equals(""))) {
            error_message = error_message + "Пароль должен быть заполнен. ";
        }

        if (error_message.equals("")) {
            DBObject object = oracleDAOFactory.getObjectDAO().getById(new BigInteger(user_id));
            if (object != null) {
                ParametersDAO parameterDAO = oracleDAOFactory.getParameterDAO();

//                User user = (User) req.getSession(false).getAttribute(PluginConst.CURRENT_USER);

                List<Parameter> paramterList = parameterDAO.getPropertyValueForObject(object.getObject_id());

                for (Parameter param : paramterList) {
                    if (param.getProperty_id().equals(namePropertyId)) {
                        param.setValue(name);
                        parameterDAO.update(param);
                    }
                    if (param.getProperty_id().equals(passwordPropertyId)) {
                        param.setValue(password);
                        parameterDAO.update(param);
                    }
                    if (param.getProperty_id().equals(typePropertyId)) {
                        param.setProperty_list_value_id(new BigInteger(user_type_id));
                        parameterDAO.update(param);
                    }
                }

                return new PluginRouter("admin-action.do"
                        + "?"
                        + PluginConst.SUBACTION
                        + "="
                        + PluginConst.GET_LIST, false);
            } else {
                throw new WrongPageRequest("Пользователя с таким id=" + user_id + " не существует. ");
            }
        } else {
            req.setAttribute(PluginConst.ERROR_MESSAGE, error_message);
            return getEditPage(req);
        }
    }

    /**
     * Метод, который позволяет перейти на страницу удаления элемента.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter getDeletePage(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String user_id = req.getParameter(PluginConst.USER_ID);
        if (user_id != null) {
            User user = null;
            user = oracleDAOFactory.getUserDAO().getById(new BigInteger(user_id));
            if (user != null) {
                User currentUser = (User) req.getSession(false).getAttribute(PluginConst.CURRENT_USER);
                if (!currentUser.getUserID().equals(user.getUserID())) {
                    req.setAttribute(PluginConst.USER, user);
                } else {
                    req.setAttribute(PluginConst.ERROR_MESSAGE,
                            "Вы пытаетесь удалить пользователя из под которого работаете в системе.");
                    return new PluginRouter("/errorpage.jsp");
                }
            } else {
                throw new WrongPageRequest("Пользователя с таким id=" + user_id + " не существует. ");
            }
            return new PluginRouter("/Users/DeleteUser.jsp");
        } else {
            throw new WrongPageRequest("ID группы атрибутов не заданно.");
        }
    }

    /**
     * Метод, удаляющий данные из базы данных.
     *
     * @param req Реквест.
     * @return PluginRouter c запрашиваемой страницей.
     * @throws DAOException Ошибка доступа к базе данных.
     * @throws WrongPageRequest Критическая ошибка в данных реквеста.
     */
    private PluginRouter deleteData(HttpServletRequest req) throws DAOException, WrongPageRequest {
        String user_id = req.getParameter(PluginConst.USER_ID);
        ObjectDAO objectDAO = oracleDAOFactory.getObjectDAO();
        UsersDAO userDAO = oracleDAOFactory.getUserDAO();
        if (user_id != null) {
            DBObject user = objectDAO.getById(new BigInteger(user_id));
            if (user != null) {
                if (userDAO.isUserAdmin(new BigInteger(user.getObject_id().toString()))) {
                    if (userDAO.getAdminCount() == 1) {
                        req.setAttribute(PluginConst.ERROR_MESSAGE, "Администратор должен быть как минимум 1!!!");
                        return getDeletePage(req);
                    }
                }
            }
            objectDAO.delete(user.getObject_id());
            return new PluginRouter("admin-action.do"
                    + "?"
                    + PluginConst.SUBACTION
                    + "="
                    + PluginConst.GET_LIST, false);
        } else {
            throw new WrongPageRequest("Пользователя с таким id=" + user_id + " не существует. ");
        }
    }
}
